<template>
  <div class="slider-line">
    <div ref="sliderBall" @mousedown.prevent="onSlide($event)" class="slider-ball"
         :style="{left: `calc(${per}% - 8px)`}">
      <div class="tips" v-if="isMoving">{{tips}}</div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'RSlider',
  data () {
    return {
      per: 0,
      tips: '',
      isMoving: false
    }
  },
  props: ['value'],
  created () {
    let [per, tips] = this.getEstimate(this.value)
    this.per = per
    this.tips = tips
  },
  methods: {
    getEstimate (value) {
      if (value <= 15) {
        return [0, '一般']
      } else if (value <= 48.34) {
        return [33.34, '良好']
      } else if (value <= 81.67) {
        return [66.67, '熟练']
      } else {
        return [100, '精通']
      }
    },
    onSlide: function (event) {
      let dom = this.$refs.sliderBall
      let initX = parseInt(event.clientX)
      let initLeft = this.per * parseInt(this.$el.clientWidth) / 100 - parseInt(dom.clientWidth)
      let maxLeft = parseInt(this.$el.clientWidth) - parseInt(dom.clientWidth) / 2
      initLeft = Number.isNaN(initLeft) ? 0 : initLeft
      dom.style.transition = ''
      this.isMoving = true
      let mouseMove = me => {
        let newLeft = parseInt(me.clientX) - initX + initLeft
        if (newLeft >= 0 && newLeft <= maxLeft) {
          dom.style.left = `${newLeft}px`
          let doneVal = parseInt(dom.style.left) * 100 / parseInt(this.$el.clientWidth)
          let [, tips] = this.getEstimate(doneVal)
          this.tips = tips
        }
      }
      document.addEventListener('mousemove', mouseMove)

      document.addEventListener('mouseup', () => {
        document.removeEventListener('mousemove', mouseMove)
        let doneVal = parseInt(dom.style.left) * 100 / parseInt(this.$el.clientWidth)
        let [finalVal] = this.getEstimate(doneVal)
        dom.style.left = finalVal > 0 ? `calc(${finalVal}% - 8px)` : '0'
        dom.style.transition = 'left 0.5s'
        this.per = finalVal
        this.isMoving = false
      }, {once: true})
    }
  },
  watch: {
    value: function (newVal) {
      this.per = newVal
    },
    per: function (newVal) {
      this.$emit('input', newVal)
    }
  }
}
</script>

<style scoped lang="less">
  @ballWidth: 16px;
  @halfWith: (@ballWidth / 2);

  .slider-line {
    height: 10px;
    width: 100px;
    background: lightgrey;
    border-radius: 5px;
    position: relative;
    margin-right: @halfWith;

    .slider-ball {
      top: -3px;
      height: @ballWidth;
      width: @ballWidth;
      background: lightskyblue;
      border-radius: @halfWith;
      position: relative;
      cursor: pointer;

      .tips {
        position: absolute;
        top: -23px;
        left: -8px;
        background: rgba(0, 0, 0, 0.8);
        width: 28px;
        padding: 2px;
        border-radius: 2px;
        color: white;
        text-align: center;

        &::selection {
          background: none
        }
      }
    }
  }
</style>
